home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Communications / pcomm / Source / script.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  3.3 KB  |  145 lines

  1. /*
  2.  * Spawn a shell with file descriptors that look like this:
  3.  *
  4.  *              +---------+
  5.  *   TTYin ---> | input   | ---> screen (& virtual screen)
  6.  *              | program |
  7.  *              +---------+
  8.  *                   |                     +---------+
  9.  *                  pipe ----------> stdin |         |
  10.  *                                         |  shell  |
  11.  *   TTYout <---------------------- stdout |         |
  12.  *                                         +---------+
  13.  *
  14.  * The input program has a routine that duplicates the TTYin and sends it
  15.  * down a pipe.  The other end of the pipe is the stdin to the shell script.
  16.  * This allows the characters to appear on the screen *and* be interpreted
  17.  * by the shell script.
  18.  */
  19.  
  20. #include <stdio.h>
  21. #include <signal.h>
  22. #include <curses.h>
  23. #include <errno.h>
  24. #include "config.h"
  25. #include "dial_dir.h"
  26. #include "status.h"
  27.  
  28. #ifdef BSD
  29. #ifndef SIGCLD
  30. #define SIGCLD SIGCHLD
  31. #endif /* SIGCLD */
  32. #include <sys/file.h>
  33. #else /* BSD */
  34. #include <fcntl.h>
  35. #endif /* BSD */
  36.  
  37. void
  38. do_script(extra)
  39. char *extra;
  40. {
  41.     extern int fd, errno;
  42.     SIG_TYPE (*istat)(), (*qstat)(), (*cstat)();
  43.     int epid, dup_pipe[2], want_out;
  44.     char buf[80], *path, *findfile();
  45.     void _exit(), error_win(), input_off(), do_input();
  46.  
  47.                     /* if empty */
  48.     if (*dir->script[dir->d_cur] == '\0')
  49.         return;
  50.                     /* find the script file */
  51.     if ((path = findfile(extra, dir->script[dir->d_cur])) == NULL) {
  52.         /*
  53.          * Fail quietly, if the script is actually a device.
  54.          */
  55.         if (chk_script(dir->script[dir->d_cur]))
  56.             return;
  57.  
  58.         sprintf(buf, "Can't locate script \"%s\"", dir->script[dir->d_cur]);
  59.         error_win(0, buf, "");
  60.         return;
  61.     }
  62.                     /* execute permission ? */
  63.     if (access(path, 1)) {
  64.         sprintf(buf, "\"%s\"", path);
  65.         error_win(0, "No execute permission on script file", buf);
  66.         return;
  67.     }
  68.                     /* create a fd for duplicating input */
  69.     if (pipe(dup_pipe) < 0)
  70.         return;
  71.  
  72.     status->dup_fd = dup_pipe[1];
  73.                     /* start input duplication */
  74.     do_input();
  75.  
  76.     if (!(epid = fork())) {
  77.                     /* create a new process group ID */
  78. #ifdef BSD
  79.         setpgrp(0, getpid());
  80. #else /* BSD */
  81.         setpgrp();
  82. #endif /* BSD */
  83.                     /* swap the stdin */
  84.         close(0);
  85.         dup(dup_pipe[0]);
  86.                     /* swap the stdout */
  87.         close(1);
  88.         dup(fd);
  89. #ifdef SETUGID
  90.         setgid(getgid());
  91.         setuid(getuid());
  92. #endif /* SETUGID */
  93.  
  94.         execl("/bin/sh", "sh", "-c", path, (char *) 0);
  95.         _exit(1);
  96.     }
  97.     istat = signal(SIGINT, SIG_IGN);
  98.     qstat = signal(SIGQUIT, SIG_IGN);
  99.     cstat = signal(SIGCLD, SIG_IGN);
  100.  
  101.     /*
  102.      * Check the keyboard while the script is being "played".  If the
  103.      * user hits the <ESC> key, then kill the entire process group
  104.      * associated with the new shell.
  105.      */
  106.     want_out = 0;
  107.     while(1) {
  108.         switch(wait_key(stdscr, 1)) {
  109.             case -1:    /* timed out */
  110.                 break;
  111.             case 27:    /* a user abort */
  112. #ifdef BSD
  113.                 killpg(epid, SIGKILL);
  114. #else /* BSD */
  115.                 kill(-epid, SIGKILL);
  116. #endif /* BSD */
  117.                 want_out++;
  118.                 break;
  119.             default:
  120.                 beep();
  121.                 break;
  122.         }
  123.         if (want_out)
  124.             break;
  125.                     /* see if the process it still active */
  126.         if ((kill(epid, 0) == -1) && errno == ESRCH) 
  127.             break;
  128.     }
  129.  
  130.     signal(SIGINT, istat);
  131.     signal(SIGQUIT, qstat);
  132.     signal(SIGCLD, cstat);
  133.                     /* shut down the duplication of input */
  134.     status->dup_fd = -1;
  135.  
  136. #ifndef SHAREDMEM
  137.     input_off();
  138. #endif /* SHAREDMEM */
  139.  
  140.     close(dup_pipe[0]);
  141.     close(dup_pipe[1]);
  142.     beep();
  143.     return;
  144. }
  145.